【初心者向け】SwaggerとAWS SAMを使ってWebAPIを簡単に作ってみた
はじめに
サーバーレス開発部の藤井元貴です。インフルエンザに怯えてます。(予防接種はしてる)
API Gatewayでは、WebAPIの作成にSwaggerを使用できます。 Swaggerを使うことで、ドキュメント内容とWebAPI仕様の一致が期待できます(齟齬がない)。
私にとってSwaggerは初めて使うため、ひとまず下記を試してみました。
- Swaggerを使ってWebAPIを作る
- AWS SAMを使う
まずはシンプルに試すため、最低限の内容です。 例えば、開発環境と本番環境(devとprod)のように分けていません。
おすすめ
- SwaggerでAPI Gatewayを定義したい人
- AWS SAMを使いたい人
- サーバーレスなWebAPIに興味がある人
環境
項目 | バージョン |
---|---|
macOS | High Sierra 10.13.6 |
AWS CLI | aws-cli/1.16.89 Python/3.6.1 Darwin/17.7.0 botocore/1.12.79 |
AWS SAM | 0.10.0 |
Docker for Mac | 18.09.1 |
Python | 3.6 |
全体概要
WebAPIを作成します。裏側にはLambdaを配置するサーバーレスな構成です。
API Gatewayの定義にSwaggerを使用し、デプロイにAWS SAMを使用します。
WebAPIの仕様
Swaggerを使う前に、まずはWebAPIの仕様を考えます。
Path | Method | 概要 |
---|---|---|
/version | GET | LambdaのPythonバージョンを取得する |
応答パラメータの例は下記とします。
{ "python": "3.6.2" }
AWS SAMプロジェクトの準備
下記コマンドでプロジェクト一式を作成します。
sam init --runtime python3.6 --name SwaggerSample
Swagger Editor
導入
こちらを参考に導入します。Dockerは便利ですね。
API定義
Swagger Editorで下記を作成しました。この内容をswagger.yaml
として、AWS SAMプロジェクトフォルダに保存します。
swagger: "2.0" info: description: "SwaggerとAPI Gatewayのサンプルです。" version: "1.0.0" title: "Swagger Sample" basePath: "/Prod" tags: - name: "Version" schemes: - "https" paths: /version: get: tags: - "Version" summary: "Pythonバージョン取得" description: "Lambdaで動いているPythonのバージョンを取得します。" consumes: - "application/json" produces: - "application/json" responses: 200: description: "successful operation" schema: $ref: "#/definitions/Version" x-amazon-apigateway-integration: uri: Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PythonVersionFunction.Arn}/invocations passthroughBehavior: when_no_templates httpMethod: POST type: aws_proxy definitions: Version: type: "object" required: - "python" properties: python: type: "string"
API Gatewayで必要となるx-amazon-apigateway-integration
を記載しています。詳細はこちらへ。
なお、下記のようなドキュメントになります。参考まで。
AWS SAM
Lambda関数
Lambda関数のコードは下記です。Pythonバージョンの文字列を返却します。
import sys import json def lambda_handler(event, context): version = f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}' return { "statusCode": 200, "body": json.dumps( {"python": version}, ), }
templateファイル
AWS SAMのtemplate.yaml
は下記です。
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: > SwaggerSample Sample SAM Template for SwaggerSample Globals: Function: Timeout: 3 Resources: PythonVersionApi: Type: AWS::Serverless::Api Properties: StageName: Prod DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: s3://cm-fujii.genki-sam-test-bucket/swagger.yaml PythonVersionFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.6 Events: HelloWorld: Type: Api Properties: Path: /version Method: get RestApiId: !Ref PythonVersionApi Outputs: PythonVersionApiUrl: Description: "API Gateway endpoint URL for Prod stage for Python Version Function" Value: !Sub "https://${PythonVersionApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/version"
Type: AWS::Serverless::Api
でAPIを明示的に定義し、S3に格納してあるyamlファイル(swagger.yaml)を指定します。
S3
コード等を格納するためのS3バケットを作成します。作成済みの場合は飛ばします。
aws s3 mb s3://cm-fujii.genki-sam-test-bucket
Swaggerファイルを格納
SwaggerファイルをS3バケットに格納します。
aws s3 cp swagger.yaml s3://cm-fujii.genki-sam-test-bucket/swagger.yaml
ビルド
下記コマンドでビルドします。
sam build
動作確認(ローカル)
まずはAPIを準備します。
sam local start-api
続いてcurlでAPIを叩きます。
$ curl http://localhost:3000/version {"python": "3.6.1"}
OKですね!
package
続いてコード一式をS3バケットにアップロードします。
sam package \ --output-template-file packaged.yaml \ --s3-bucket cm-fujii.genki-sam-test-bucket
deploy
最後にデプロイします。
sam deploy \ --template-file packaged.yaml \ --stack-name SwaggerSample \ --capabilities CAPABILITY_IAM
動作確認
作成したWebAPIのエンドポイントを確認します。
Web画面ポチポチでも良いですが、せっかくなのでコマンドを使います。
$ aws cloudformation describe-stacks --stack-name SwaggerSample --query 'Stacks[].Outputs' [ [ { "OutputKey": "PythonVersionApiUrl", "OutputValue": "https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/Prod/version", "Description": "API Gateway endpoint URL for Prod stage for Python Version Function" } ] ]
では、作成したWebAPIを叩いてみましょう!
$ curl https://hogehoge.execute-api.ap-northeast-1.amazonaws.com/Prod/version {"python": "3.6.8"}
Python3系で最新の3.6.8が使用されていました。
ハマったこと
Swaggerの記載で下記にハマりました。
definitions
にexample
を記載すると、sam deploy
が失敗する- WebAPIのMethodがGETでも、
x-amazon-apigateway-integration
のhttpMethod
はPOSTを指定する
どちらもAWS(AWS SAM、API Gateway、Lambda)との連携部分です。辛かった……。
Swagger Editorですべて頑張らずに、AWSのWeb画面でAPI Gatewayをポチポチ作成したあと、Swagger形式でエクスポートするのも有効です。むしろこのほうが効率良さそう。
さいごに
SwaggerとAWSの組み合わせは、使い倒すほどハマる点が増えそうに感じましたが、Infrastructure as Codeは良いですね!! 楽しいです!